/* $Header: dig_path.c,v 2.3 20/3./7. 9.:4.:1. dryden Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME: dig_path.c                                             */
/* ============                                                        */
/*                                                                     */
/* Author:  Bob Cook                                                   */
/*                                                                     */
/* MODULE PURPOSE: This module will handle the buffering,              */
/*     and compressing for the digital data.  It receives              */
/*     signed 48 bit data points from the Signal Path. The             */
/*     data is compressed using a second order difference              */
/*     modulation scheme.                                              */
/*                                                                     */
/*      The flow of data through the functions in this module are      */
/*      given below.  SIG_PATH and CMD_PROC are processes before and   */
/*      after this module.  SigBuf is the main data buffers.  Also     */
/*      there are three channels of data (Signals 1, 2 and P), so      */
/*      three buffers exist for SigBuf (SigBuf1, SigBuf2 and SigBufP). */
/*                                                                     */
/*       SIG_PATH --> CompressAndStore() --> SigBuf --> CMD_PROC       */
/*                                                                     */
/* WARNING: This module was designed with the assumption that          */
/*          CompressAndStore is run at a higher priority then          */
/*          the process that retrieve the data so CompressAndStore     */
/*          does not turn interrupts off.                              */
/*                                                                     */
/*                                                                     */
/* ENHANCEMENTS:                                                       */
/*       1) Add a method which will allow the user to configure RAM    */
/*          allocation between SigBuf1 and SigBuf2. An alternative     */
/*          and better method would be to dynamically allocate memory  */
/*          in 1K chunks for SigBuf1 and SigBuf2.  The chunks of       */
/*          memory would later be returned  as data was removed from   */
/*          the buffer.  This would allow the best use of memory, but  */
/*          will be much more difficult to implement.                  */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

/*
 *  The purpose of data compression is to reduce the storage space needed
 *  to store the chromatographic data while it is waiting to be sent to
 *  the host system.
 *  The compression algorithm makes use of the fact that data values change
 *  by a small amount from one data point to the next so the slope is
 *  slowly changing.
 *
 * The main data buffers will be implemented as three circular queues,
 * SigBuf1 for Signal 1, SigBuf2 for Signal 2, etc.  If a buffer becomes
 * full (buffer overflow) no new data may be entered into the buffer
 * until the buffer is initialized.  This will ensure the integrity
 * of the data received by the Host Computer.
 *
 *  The 48 bit integer from the main data buffer may be formatted in
 *  one of three possible ways:
 *         1) Binary - 6 byte integer IEEE Format (Motorola Format)
 *         2) Hex - converts binary part of output to hexadecimal ASCII
 *         3) Compressed - typically 2 bytes per point converted to
 *                         4 bytes of hex
 *         4) Decimal
 *
 *
 */

/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/


#include  <typedefs.h>
#include  <p_wkfile.h>
#include  <wkfile.h>
#include  <ramps.h>
#include  <zone_config.h>
#include  <zone_status.h>
#include  <status.h>
#include  <config.h>
#include <error.h>
#include <exception.h>
#include <err_handler.h>

#include <sig_types.h>
#include <sigpath.h>
#include <dig_path.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/


/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/

/* create control blocks to use with Compress and Uncompress */
SIGNAL_CB_TYPE compress_cb[NUM_SIGNALS];
SIGNAL_CB_TYPE uncompress_cb[NUM_SIGNALS];
SIGBUF_TYPE  SigBuf_V[NUM_SIGNALS]; /* create vars for SigBuf1, SigBuf2 & SigBufP*/
U_INT16 DigitalPathTestMode;
POINT_TYPE Test_8Byte[2];
U_INT32 DPT_Shift_Num[2];
U_INT8 DPT_Subtract[2];

/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/


/* when debugging make variables global for emulator testing */
#ifdef BC_DIG_DEBUG
#   define SCOPE
#else
#   define  SCOPE  static
#endif

/*****************************/
/*   STATIC VARIABLES        */
/*****************************/


U_INT16 Compress_Count[NUM_SIGNALS];

#ifndef mccabe
#pragma SECTION UDATA=DRam
#endif
SCOPE INT16  SigBuf1[SIGBUF1_SIZE];      /* create main data buffers */
SCOPE INT16  SigBuf2[SIGBUF2_SIZE];
SCOPE INT16  SigBufP[SIGBUFP_SIZE];
#ifndef mccabe
#pragma SECTION UNDO
#endif



/* debug buffers */

#ifdef BC_DIG_DEBUG
#ifndef mccabe
#pragma SECTION UDATA=DRam
#endif

#define Num_Entries 1024  /* used only for size of test buffers */
U_INT8  TMP_SignalBuf[Num_Entries];
U_INT8  *pTMP_SignalBuf;
U_INT8  *pTMP_SignalBuf_End;
U_INT16  TMP_CountBuf[Num_Entries];
U_INT16  *pTMP_CountBuf;
U_INT16  *pTMP_CountBuf_End;
INT32  TMP_CASBuf[Num_Entries];
INT32  *pTMP_CASBuf;
INT32  *pTMP_CASBuf_End;
INT32  TMP_BMBuf[256];

#ifndef mccabe
#pragma SECTION UNDO
#endif
#endif



/*****************************/
/*   MACROS                  */
/*****************************/




/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/

/***********************************************************************/
/*                                                                     */
/*     Utilities used by other functions to handle 6 byte data         */
/*                                                                     */
/***********************************************************************/

void Add64(POINT_TYPE *num1,POINT_TYPE *num2)
{
/* 64 bit add: num1 = num1 + num2 */
/* since size of data is 5 bytes don't need to worry about overflow */
(void) num1;
(void) num2;

printf("call Add64\n");
#ifndef mccabe
#pragma ASM
   MOVEA.L (S_num1,A6),A0
   MOVEA.L (S_num2,A6),A1
   ADDQ.L  #8,A0              ; set up for addx instruction
   ADDQ.L  #8,A1              ; point to one beyond LS Long word of number
   MOVE    #0,CCR
   ADDX.L  -(A1),-(A0)        ; add with X bit
   ADDX.L  -(A1),-(A0)
#pragma END_ASM
#endif
}

void Sub64(POINT_TYPE *num1,POINT_TYPE *num2)
{
/* 64 bit subtract: num1 = num1 - num2 */
/* since size of data is 5 bytes don't need to worry about underflow */
(void) num1;
(void) num2;

printf("call Sub64\n");
#ifndef mccabe
#pragma ASM
   MOVEA.L (S_num1,A6),A0
   MOVEA.L (S_num2,A6),A1
   ADDQ.L  #8,A0              ; point to one beyond LS Long word of number
   ADDQ.L  #8,A1
   MOVE    #0,CCR             ; clear X bit
   SUBX.L  -(A1),-(A0)        ; subtract LS Long word
   SUBX.L  -(A1),-(A0)        ; subtract with X the MS Long word
#pragma END_ASM
#endif
}

void Copy64(POINT_TYPE *from,POINT_TYPE *to)
{
/* 64 bit copy from "from" to "to" */
(void) to;
(void) from;

printf("call Copy64\n");
#ifndef mccabe
#pragma ASM
   MOVEA.L (S_to,A6),A0
   MOVEA.L (S_from,A6),A1
   MOVE.L  (A1),(A0)
   MOVE.L  (A1,4),(A0,4)
#pragma END_ASM
#endif
}


void ConvSigToDig(DIG48 *sig_data, POINT_TYPE *dig_data)
{
/* read 48 bit signal point and shift it by 8 bits */
/*    then   save it as 64 bit number */
/*    then   shift the 64 bit number to right by 11 bits */

(void) sig_data;
(void) dig_data;
printf("call ConvSigToDig\n");
#ifndef mccabe
#pragma ASM
   MOVE.L     D2,-(A7)             ; save registers
   MOVEA.L    (S_sig_data,A6),A0
   MOVEA.L    (S_dig_data,A6),A1
   MOVE.L     (A0,2),(A1,4)       ; copy 32 LSBits
   MOVEA.W    (A0),A0             ; sign extend MSBits
   MOVE.L     A0,(A1)

              ; shift the 64 bit number to right by 11 bits

   MOVE.L    (A1,4),D0           ; D0 = LSbits of number
   MOVE.L    (A1),D1             ; D1 = MSbits of number
   MOVE.W    #11,D2              ; number of bits to shift
R_SHIFT
   ASR.L     #1,D1               ; shift right preserve sign
   ROXR.L    #1,D0               ; shift right through X for MS Bit
   SUBQ.W    #1,D2               ; decrement count
   BNE       R_SHIFT
   MOVE.L    D0,(A1,4)           ; save new number LSBits
   MOVE.L    D1,(A1)             ; MSBits
   MOVE.L    (A7)+,D2            ; restore registers
#pragma END_ASM
#endif
}


/***********************************************************************/
/*                                                                     */
/*     Utilities used by other functions for data compression          */
/*                                                                     */
/***********************************************************************/

void Compress_Diff2(U_INT8 signal)
{
/* determine the second order difference modulation for siginal given
 *   Algorithm:
 *     diff = point - point_last
 *     diff2 = diff - diff_last
 *     diff_last = diff
 *     point_last = point
 *
 *   Code
 *     diff = point
 *     diff = diff - point_last
 *     diff = diff2
 *     diff2 = diff2 - diff_last
 *     diff_last = diff
 *     point_last = point
 */

   Copy64(&compress_cb[signal].point,&compress_cb[signal].diff);
   Sub64(&compress_cb[signal].diff,&compress_cb[signal].point_last);
   Copy64(&compress_cb[signal].diff,&compress_cb[signal].diff2);
   Sub64(&compress_cb[signal].diff2,&compress_cb[signal].diff_last);
   Copy64(&compress_cb[signal].diff,&compress_cb[signal].diff_last);
   Copy64(&compress_cb[signal].point,&compress_cb[signal].point_last);
}

void ConvCompressTo64(INT16 *compr_data, POINT_TYPE *diff2_data)
/* sign extend compressed number to 64 bits
 */
{
(void) compr_data;
(void) diff2_data;
printf("call ConvCompressTo64\n");
#ifndef mccabe
#pragma ASM
   MOVEA.L    (S_compr_data,A6),A0
   MOVEA.L    (S_diff2_data,A6),A1
   MOVEA.W    (A0),A0             ; sign extend MSBits
   TST        A0                  ; sign extend MS Long if negitive
   BMI        NEGITIVE
   MOVE.L     A0,(A1,4)
   CLR.L      (A1)
   BRA        DONE
NEGITIVE
   MOVE.L     A0,(A1,4)
   CLR.L      (A1)
   NOT.L      (A1)
DONE
#pragma END_ASM
#endif
}

void Uncompress_Diff2(U_INT8 signal)
{
/* uncompress a second order difference modulationed point for siginal given
 *   Algorithm:
 *    Copy = diff2 + diff_last
 *     point = diff + point_last
 *     diff_last = diff
 *     point_last = point
 *
 *   Code
 *     diff_last = diff_last + diff2
 *     point_last = point_last + diff_last
 *     point = point_last
 */

   Add64(&uncompress_cb[signal].diff_last,&uncompress_cb[signal].diff2);
   Add64(&uncompress_cb[signal].point_last,&uncompress_cb[signal].diff_last);
   Copy64(&uncompress_cb[signal].point_last,&uncompress_cb[signal].point);
}

void InitCompression(U_INT8 signal)
{
   /* initialize the control block for compression and uncompression */
   compress_cb[signal].point.hi = 0;
   compress_cb[signal].point.lo = 0;
   compress_cb[signal].point_last.hi = 0;
   compress_cb[signal].point_last.lo = 0;
   compress_cb[signal].diff.hi = 0;
   compress_cb[signal].diff.lo = 0;
   compress_cb[signal].diff_last.hi = 0;
   compress_cb[signal].diff_last.lo = 0;
   compress_cb[signal].diff2.hi = 0;
   compress_cb[signal].diff2.lo = 0;

   uncompress_cb[signal].point.hi = 0;
   uncompress_cb[signal].point.lo = 0;
   uncompress_cb[signal].point_last.hi = 0;
   uncompress_cb[signal].point_last.lo = 0;
   uncompress_cb[signal].diff.hi = 0;
   uncompress_cb[signal].diff.lo = 0;
   uncompress_cb[signal].diff_last.hi = 0;
   uncompress_cb[signal].diff_last.lo = 0;
   uncompress_cb[signal].diff2.hi = 0;
   uncompress_cb[signal].diff2.lo = 0;
}

void ResetCompress(U_INT8 signal)
{
   /* reset control block after a full data point is stored in buffer */
   Copy64(&compress_cb[signal].point,&compress_cb[signal].point_last);
   compress_cb[signal].diff_last.hi = 0;
   compress_cb[signal].diff_last.lo = 0;

}

void ResetUncompress(U_INT8 signal)
{
   /* reset control block after a full data point is received from buffer */
   /* Outside this function, point_last must be set to the current point. */
   uncompress_cb[signal].diff_last.hi = 0;
   uncompress_cb[signal].diff_last.lo = 0;
}




/***********************************************************************/
/* FUNCTION: InitSignal_1_DigitalPath                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Initialize all variables used by the Signal 1 digital      */
/*          data path                                                  */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* CALLS: none                                                         */
/*                                                                     */
/* LIMITATIONS:  none                                                  */
/*                                                                     */
/***********************************************************************/

#ifndef mccabe
#pragma SECTION PROG=boot
#endif

void InitSignal_1_DigitalPath(void)
{
   SigBuf_Point_Count[SIGNAL1] = 0;
   SigBuf_Overflow[SIGNAL1] = FALSE;

   SigBuf_V[SIGNAL1].pbuffer = SigBuf1;
   SigBuf_V[SIGNAL1].pfront = SigBuf_V[SIGNAL1].prear = SigBuf1;
   SigBuf_V[SIGNAL1].size = SIGBUF1_SIZE;
   SigBuf_V[SIGNAL1].count = 0;
   SigBuf_V[SIGNAL1].last_in = 0;
   SigBuf_V[SIGNAL1].last_out = 0;

   Acq_On[SIGNAL1] = FALSE;

   InitCompression(SIGNAL1);

   /* initialize count used to periodically send full point */
   Compress_Count[SIGNAL1] = 0;

   /* initialize variables used in digital test signal */
   DigitalPathTestMode = 0;
   Test_8Byte[0].hi = 0;
   Test_8Byte[0].lo = 0;
   DPT_Subtract[0] = 0;
   DPT_Shift_Num[0] = 0;

   Test_8Byte[1].hi = 0;
   Test_8Byte[1].lo = 0;
   DPT_Subtract[1] = 0;
   DPT_Shift_Num[1] = 0;


/* debug buffers */
#ifdef BC_DIG_DEBUG
   pTMP_SignalBuf = (U_INT8  *)TMP_SignalBuf;
   pTMP_SignalBuf_End = (U_INT8  *)&TMP_SignalBuf[Num_Entries-1];
   pTMP_CountBuf = (U_INT16  *)TMP_CountBuf;
   pTMP_CountBuf_End = (U_INT16  *)&TMP_CountBuf[Num_Entries-1];
   pTMP_CASBuf =  (INT32   *)TMP_CASBuf;
   pTMP_CASBuf_End =  (INT32   *)&TMP_CASBuf[Num_Entries-1];
   pTMP_BMBuf = (INT32   *)TMP_BMBuf;
   pTMP_BMBuf_End = (INT32   *)&TMP_BMBuf[255];
#endif
}

#ifndef mccabe
#pragma SECTION UNDO
#endif


/***********************************************************************/
/* FUNCTION: InitSignal_2_DigitalPath                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Initialize all variables used by the Signal 2 digital      */
/*          data path                                                  */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* CALLS: none                                                         */
/*                                                                     */
/* LIMITATIONS: none                                                   */
/*                                                                     */
/***********************************************************************/

#ifndef mccabe
#pragma SECTION PROG=boot
#endif

void InitSignal_2_DigitalPath(void)
{
   SigBuf_Point_Count[SIGNAL2] = 0;
   SigBuf_Overflow[SIGNAL2] = FALSE;

   SigBuf_V[SIGNAL2].pbuffer = SigBuf2;
   SigBuf_V[SIGNAL2].pfront = SigBuf_V[SIGNAL2].prear = SigBuf2;
   SigBuf_V[SIGNAL2].size = SIGBUF2_SIZE;
   SigBuf_V[SIGNAL2].count = 0;
   SigBuf_V[SIGNAL2].last_in = 0;
   SigBuf_V[SIGNAL2].last_out = 0;

   Acq_On[SIGNAL2] = FALSE;

   InitCompression(SIGNAL2);

   /* initialize count used to periodically send full point */
   Compress_Count[SIGNAL2] = 0;

   /* initialize variables used in digital test signal */
   DigitalPathTestMode = 0;
   Test_8Byte[0].hi = 0;
   Test_8Byte[0].lo = 0;
   DPT_Subtract[0] = 0;
   DPT_Shift_Num[0] = 0;

   Test_8Byte[1].hi = 0;
   Test_8Byte[1].lo = 0;
   DPT_Subtract[1] = 0;
   DPT_Shift_Num[1] = 0;
}

#ifndef mccabe
#pragma SECTION UNDO
#endif


/***********************************************************************/
/* FUNCTION: InitSignal_P_DigitalPath                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Initialize all variables used by the Signal P digital      */
/*          data path                                                  */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* CALLS: none                                                         */
/*                                                                     */
/* LIMITATIONS: none                                                   */
/*                                                                     */
/***********************************************************************/

#ifndef mccabe
#pragma SECTION PROG=boot
#endif

void InitSignal_P_DigitalPath(void)
{
   SigBuf_Point_Count[SIGNALP] = 0;
   SigBuf_Overflow[SIGNALP] = FALSE;

   SigBuf_V[SIGNALP].pbuffer = SigBufP;
   SigBuf_V[SIGNALP].pfront = SigBuf_V[SIGNALP].prear = SigBufP;
   SigBuf_V[SIGNALP].size = SIGBUFP_SIZE;
   SigBuf_V[SIGNALP].count = 0;
   SigBuf_V[SIGNALP].last_in = 0;
   SigBuf_V[SIGNALP].last_out = 0;

   Acq_On[SIGNALP] = FALSE;

   InitCompression(SIGNALP);

   /* initialize count used to periodically send full point */
   Compress_Count[SIGNALP] = 0;

   /* initialize variables used in digital test signal */
   DigitalPathTestMode = 0;
   Test_8Byte[0].hi = 0;
   Test_8Byte[0].lo = 0;
   DPT_Subtract[0] = 0;
   DPT_Shift_Num[0] = 0;

   Test_8Byte[1].hi = 0;
   Test_8Byte[1].lo = 0;
   DPT_Subtract[1] = 0;
   DPT_Shift_Num[1] = 0;
}

#ifndef mccabe
#pragma SECTION UNDO
#endif


/***********************************************************************/
/* FUNCTION: ResetBufIfSingleMode                                      */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Initialize all variables used by the Signal 1 or 2 digital */
/*          data path if Acq_Mode is set to SinGLe.                    */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*    U_INT16 Acq_Mode[]                                               */
/*                                                                     */
/* CALLS: InitSignal_1_DigitalPath                                     */
/*        InitSignal_2_DigitalPath                                     */
/*        InitSignal_P_DigitalPath                                     */
/*                                                                     */
/* LIMITATIONS: none                                                   */
/*                                                                     */
/***********************************************************************/
void ResetBufIfSingleMode(void)
{
   if(Acq_Mode[SIGNAL1] == SGL)
   {
      InitSignal_1_DigitalPath();
      ClearNewException(SIGBUF1_OVERFLOW);
   }
   if(Acq_Mode[SIGNAL2] == SGL)
   {
      InitSignal_2_DigitalPath();
      ClearNewException(SIGBUF2_OVERFLOW);
   }
   if(Acq_Mode[SIGNALP] == SGL)
   {
      InitSignal_P_DigitalPath();
/* revisit - need to create a new exception for signal P buffer overflow */
/*    ClearNewException(SIGBUFP_OVERFLOW);                               */
   }
}



/***********************************************************************/
/* FUNCTION: DigitalPathTest                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: This is a function installed for development testing       */
/*          of the digial path of IQ.  It was created by modifying     */
/*          CompressAndStore to save a triangle wave form in the       */
/*          Data buffer.  The points are added to the data buffer      */
/*          at the rate set by the signal's data rate.                 */
/*          When CompressAndStore is called by the signal path         */
/*          this function will ignore the data coming from the         */
/*          signal path and put test data into the data buffer.        */
/*          Function is called with Signal number (1 or 2), number     */
/*          of points, and location of data.  The data is compressed   */
/*          using a second order difference modulation technique and   */
/*          stored in the buffer indicated. If the buffer becomes      */
/*          full the new data will be thrown away.                     */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/*                                                                     */
/***********************************************************************/
#ifndef mccabe
#pragma SECTION PROG=SysCode
#endif


void DigitalPathTest(U_INT8 Signal,U_INT16 Data_Count)
{
   DIG48 *pDigital_Data;
   U_INT16   i,count;
   DIG48  test_pt[2][2];  /* size for for 200 hz max */
   POINT_TYPE inc_8byte[2];


   /*  to increase output by one count increase inc_8byte by:
    *     inc_8byte.hi[Signal] = 0;
    *     inc_8byte.lo[Signal] = 0x0800;
    */

   for(count = 0; count < Data_Count ;count++)
   {

      /* setup point buffer and then increment to next point */

      /* remove lower 11 garbage bits so they are not carried forward */
      Test_8Byte[Signal].lo = Test_8Byte[Signal].lo & 0xFFFFF800;

      test_pt[Signal][count].num.hi_word = (U_INT16)Test_8Byte[Signal].hi;
      test_pt[Signal][count].num.lo_long = Test_8Byte[Signal].lo;


      /* setup next increment */
      /* if increment will be less than one count reset to max */
      DPT_Shift_Num[Signal] =  DPT_Shift_Num[Signal] >> 3;
      /* remove lower 11 garbage bits so they are not carried forward */
      DPT_Shift_Num[Signal] =  DPT_Shift_Num[Signal] & 0xFFFFF800;
      if(DPT_Shift_Num[Signal] <= 0x0800)
      {
         DPT_Shift_Num[Signal] = DPT_MAX_INCR;
      }
      inc_8byte[Signal].lo =  DPT_Shift_Num[Signal];
      inc_8byte[Signal].hi = 0;

      /* add or subtract increment from test signal */
      if (DPT_Subtract[Signal] == 1)
      {
         Sub64(&Test_8Byte[Signal],&inc_8byte[Signal]);
      }
      else
      {
         Add64(&Test_8Byte[Signal],&inc_8byte[Signal]);
      }

      /* check for data getting to positive */
      if( (INT32)Test_8Byte[Signal].hi > (INT32)0x00007FFF )
      {
         DPT_Subtract[Signal] = 1;
         /* remove lower 11 garbage bits so they are not carried forward */
         Test_8Byte[Signal].lo = Test_8Byte[Signal].lo & 0xFFFFF800;
         /* compensate for previous add */
         Sub64(&Test_8Byte[Signal],&inc_8byte[Signal]);
         /* remove lower 11 garbage bits so they are not carried forward */
         Test_8Byte[Signal].lo = Test_8Byte[Signal].lo & 0xFFFFF800;
         Sub64(&Test_8Byte[Signal],&inc_8byte[Signal]);
      }

      /* check for data getting to negitive */
      if( (INT32)Test_8Byte[Signal].hi <= (INT32)0xFFFF8000 )
      {
         if( ((INT32)Test_8Byte[Signal].hi == (INT32)0xFFFF8000) &&
                  ((U_INT32)Test_8Byte[Signal].lo >= (U_INT32)0x00040000) )
         {
             ; /* data within proper range */
         }
         else
         {
            DPT_Subtract[Signal] = 0;
            /* remove lower 11 garbage bits so they are not carried forward */
            Test_8Byte[Signal].lo = Test_8Byte[Signal].lo & 0xFFFFF800;
            /* compensate for previous subtract */
            Add64(&Test_8Byte[Signal],&inc_8byte[Signal]);
            /* remove lower 11 garbage bits so they are not carried forward */
            Test_8Byte[Signal].lo = Test_8Byte[Signal].lo & 0xFFFFF800;
            Add64(&Test_8Byte[Signal],&inc_8byte[Signal]);
         }
      }
   }


   pDigital_Data = &test_pt[Signal][0];

   for (i=0; i< Data_Count; i++)
   {
      /* Make sure there are at least 6 words of space in buffer so all */
      /*    puts will be successful. Also check for overflow condition. */
      if (  (SigBuf_Overflow[Signal] == FALSE) &&
            (SigBuf_V[Signal].count <= SigBuf_V[Signal].size - 6) )
      {
         switch((U_INT32)pDigital_Data->data.hi_long)
         {
         case START_SIGNAL_MARKER:   /* 0x80000000 */

             /* place compressed start marker in buffer */
             PutBuf(SigBuf_V[Signal], COMPRESS_START_MARKER);

             /* get start delta count */
             i++;
             pDigital_Data++;
             PutBuf(SigBuf_V[Signal],
                              (INT16)((pDigital_Data->data.hi_long)>>16));
             PutBuf(SigBuf_V[Signal],(INT16)(pDigital_Data->data.hi_long));

             /* get first data point and store uncompressed */
             i++;
             pDigital_Data++;

             ConvSigToDig(pDigital_Data, &compress_cb[Signal].point);
             ResetCompress(Signal);
             PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.hi);
             PutBuf(SigBuf_V[Signal],
                   (INT16)(compress_cb[Signal].point.lo>>16));
             PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.lo);
             break;
         case  STOP_SIGNAL_MARKER:     /*  0x80000001 */
             PutBuf(SigBuf_V[Signal], COMPRESS_STOP_MARKER);
             break;
         case  START_STOP_SIGNAL_MARKER:  /* 0x80000002  */
             PutBuf(SigBuf_V[Signal], COMPRESS_START_STOP_MARKER);
             break;
         default:
            ConvSigToDig(pDigital_Data, &compress_cb[Signal].point);
            Compress_Diff2(Signal);
            /* First check if diff2 is contained in lower long then check */
            /*     if it will fit in 2 bytes          */
            if (((compress_cb[Signal].diff2.hi +
                 ((U_INT32)compress_cb[Signal].diff2.lo >> 31)) == 0) &&
                 ((INT32)compress_cb[Signal].diff2.lo < 32752 /* 0x7FF0 */) &&
                 ((INT32)compress_cb[Signal].diff2.lo >= -32768 /*0x8000*/) &&
                 ( Compress_Count[Signal] < MAX_COMPRESS_COUNT) )

            {
               /* store (INT16) diff2.lo */
               PutBuf(SigBuf_V[Signal], (INT16)compress_cb[Signal].diff2.lo);
               Compress_Count[Signal]++;
            }
            else
            {
               /* store marker and full point */
               PutBuf(SigBuf_V[Signal], COMPRESS_FULL_POINT_MARKER);
               PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.hi);
               PutBuf(SigBuf_V[Signal],
                          (INT16)(compress_cb[Signal].point.lo >> 16));
               PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.lo);
               Compress_Count[Signal] = 0;
               ResetCompress(Signal);
            }
            break;
         }  /* switch */

         /*
          * Increase buffer count.
          *      Count includes:
          *            1. data points
          *            2. stop markers
          *            3. stop/start markers
          */
         SigBuf_Point_Count[Signal]++;
         pDigital_Data++;
      }
      else
      {
         /* Buffer is full, so make sure overflow flag is set and return. */
         if (SigBuf_Overflow[Signal] == FALSE)
         {
            /* Set overflow flag, stop acq and notify exception occurred. */
            SigBuf_Overflow[Signal] = TRUE;
            Acq_On[Signal] = FALSE;
            /* ASSUMING: two signals 1 or 2 */
            SetNewException( (Signal == SIGNAL1) ? SIGBUF1_OVERFLOW :
                                                   SIGBUF2_OVERFLOW,0,0 );
         }
         else
         {
            /* acquisition must have been turned on during an overflow */
            /*      condition so turn it off again */
            Acq_On[Signal] = FALSE;
         }
      }
   }
}

#ifndef mccabe
#pragma SECTION UNDO
#endif


/***********************************************************************/
/* FUNCTION: CompressAndStore                                          */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Called by SigPath within the 512 interrupt routine.        */
/*          Function is called with Signal number (1 or 2), number     */
/*          of points, and location of data.  The data is compressed   */
/*          using a second order difference modulation technique and   */
/*          stored in the buffer indicated. If the buffer becomes      */
/*          full the new data will be thrown away.                     */
/*                                                                     */
/* RETURNED VALUE: none                                                */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*    U_INT16 Acq_On[]: flag indicating if data acquisition is ON      */
/*    U_INT32 SigBuf_Point_Count[]: number points and STOP and         */
/*                             START/STOP markers in SigBuf buffer     */
/*    U_INT16 SigBuf_Overflow[]: indicates SigBuf buf has overflowed   */
/*                                                                     */
/* FILE SCOPE STATICS USED:                                            */
/*                                                                     */
/*          SigBuf_V data structure variables:                         */
/*                                                                     */
/*                 READ           MODIFIED                             */
/*                 ----           --------                             */
/*                 count          count                                */
/*                 last_in        last_in                              */
/*                 prear          prear                                */
/*                 size                                                */
/*                 pbuffer                                             */
/*                                                                     */
/* CALLS:  MACRO - PutBuf                                              */
/*         SetException                                                */
/*                                                                     */
/* LIMITATIONS:                                                        */
/* WARNINGS: SigBuf_V.count is modified outside of this function.      */
/*           SigBuf_Point_Count is modified outside of this function.  */
/*                                                                     */
/***********************************************************************/
#ifndef mccabe
#pragma SECTION PROG=SysCode
#endif



void CompressAndStore(U_INT8 Signal,DIG48 *pDigital_Data,U_INT16 Data_Count)
{
   U_INT16   i;

#if 0
   /* debug buffers */
   {
       if ((pTMP_CASBuf < (pTMP_CASBuf_End-Data_Count)) && (Signal == SIGNAL1))
       {
          for (i=0; i< Data_Count; i++)
          {
             *pTMP_CASBuf = (pDigital_Data+i)->data.hi_long;
             pTMP_CASBuf++;
             *pTMP_CASBuf = (pDigital_Data+i)->data.lo_word;
             pTMP_CASBuf++;
          }
          *pTMP_SignalBuf++ = Signal;
          *pTMP_CountBuf++ = Data_Count;
       }
   }
#endif

if(DigitalPathTestMode)
{
   DigitalPathTest(Signal,Data_Count);
}
else
{
   for (i=0; i< Data_Count; i++)
   {
      /* Make sure there are at least 6 words of space in buffer so all */
      /*    puts will be successful. Also check for overflow condition. */
      if (  (SigBuf_Overflow[Signal] == FALSE) &&
            (SigBuf_V[Signal].count <= SigBuf_V[Signal].size - 6) )
      {
         switch((U_INT32)pDigital_Data->data.hi_long)
         {
         case START_SIGNAL_MARKER:   /* 0x80000000 */

             /* place compressed start marker in buffer */
             PutBuf(SigBuf_V[Signal], COMPRESS_START_MARKER);

             /* get start delta count */
             i++;
             pDigital_Data++;
             PutBuf(SigBuf_V[Signal],
                              (INT16)((pDigital_Data->data.hi_long)>>16));
             PutBuf(SigBuf_V[Signal],(INT16)(pDigital_Data->data.hi_long));

             /* get first data point and store uncompressed */
             i++;
             pDigital_Data++;

             ConvSigToDig(pDigital_Data, &compress_cb[Signal].point);
             ResetCompress(Signal);
             PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.hi);
             PutBuf(SigBuf_V[Signal],
                       (INT16)(compress_cb[Signal].point.lo>>16));
             PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.lo);
             break;
         case  STOP_SIGNAL_MARKER:     /*  0x80000001 */
             PutBuf(SigBuf_V[Signal], COMPRESS_STOP_MARKER);
             break;
         case  START_STOP_SIGNAL_MARKER:  /* 0x80000002  */
             PutBuf(SigBuf_V[Signal], COMPRESS_START_STOP_MARKER);
             break;
         default:
            ConvSigToDig(pDigital_Data, &compress_cb[Signal].point);
            Compress_Diff2(Signal);
            /* First check if diff2 is contained in lower long then check */
            /*     if it will fit in 2 bytes          */
            if (((compress_cb[Signal].diff2.hi +
                 ((U_INT32)compress_cb[Signal].diff2.lo >> 31)) == 0) &&
                 ((INT32)compress_cb[Signal].diff2.lo < 32752 /* 0x7FF0 */) &&
                 ((INT32)compress_cb[Signal].diff2.lo >= -32768 /*0x8000*/) &&
                 ( Compress_Count[Signal] < MAX_COMPRESS_COUNT) )
            {
               /* store (INT16) diff2.lo */
               PutBuf(SigBuf_V[Signal], (INT16)compress_cb[Signal].diff2.lo);
               Compress_Count[Signal]++;
            }
            else
            {
               /* store marker and full point */
               PutBuf(SigBuf_V[Signal], COMPRESS_FULL_POINT_MARKER);
               PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.hi);
               PutBuf(SigBuf_V[Signal],
                          (INT16)(compress_cb[Signal].point.lo >> 16));
               PutBuf(SigBuf_V[Signal],(INT16)compress_cb[Signal].point.lo);
               ResetCompress(Signal);
               Compress_Count[Signal] = 0;
            }
            break;
         }  /* switch */

         /*
          * Increase buffer count.
          *      Count includes:
          *            1. data points
          *            2. stop markers
          *            3. stop/start markers
          */
         SigBuf_Point_Count[Signal]++;
         pDigital_Data++;
      }
      else
      {
         /* Buffer is full, so make sure overflow flag is set and return. */
         if (SigBuf_Overflow[Signal] == FALSE)
         {
            /* Set overflow flag, stop acq and notify exception occurred. */
            SigBuf_Overflow[Signal] = TRUE;
            Acq_On[Signal] = FALSE;
            /* ASSUMING: two signals 1 or 2 */
/*  Call to SetNewException moved to sx_cmds.c
            SetNewException( (Signal == SIGNAL1) ? SIGBUF1_OVERFLOW :
                                                   SIGBUF2_OVERFLOW,0,0 );
    This allows the buffer to overflow without setting an exception,
    unless the host tries to read data from the buffer after the
    overflow has occurred                                                */
         }
         else
         {
            /* acquisition must have been turned on during an overflow */
            /*      condition so turn it off again */
            Acq_On[Signal] = FALSE;
         }
      }
   }
} /*  if(DigitalPathTestMode)  */
}

#ifndef mccabe
#pragma SECTION UNDO
#endif


